﻿using NUnitForVSTS;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Reflection;
using System;

// We are using multiple namespaces with muliple classes with the same name, different meaning
// Therefore some alliasses to improve clarity
using TestTarget = NUnitTest.UnitTest.Targets;
using NUnitSide = NUnit.Core;
using MSTestSide = Microsoft.VisualStudio.TestTools.Common;
using System.IO;
using System.Data;

namespace NUnitForVSTS.NUnitTest.UT
{
    /// <summary>
    ///This is a test class for NUnitTestElementTest and is intended
    ///to contain all NUnitTestElementTest Unit Tests
    ///</summary>
    [TestClass()]
    public class UnitTestElementTest
    {
        /// <summary>
        ///A test for TestType
        ///</summary>
        [TestMethod()]
        public void TestTypeTestAssembly()
        {
            Type testClassType = typeof(TestTarget.TestFixtureSetupCorrect);
            MethodInfo testMethod = testClassType.GetMethod("HasBeenSetup");

            DummyTest test = new DummyTest();
            test.TestName = new NUnitSide.TestName();

            test.TestName.FullName = testClassType.FullName + "." + testMethod.Name;
            test.TestName.Name = testMethod.Name;
            test.TestType = testClassType.FullName;
            Assembly assembly = testClassType.Assembly;

            UnitTest target = new UnitTest(test, assembly.Location);
            MSTestSide.TestType actual;
            actual = target.TestType;
            Assert.AreEqual(actual.Id.ToString("N"), "d6af2caead694f6b94e914e2609e2389", "Should generate correct Id");
        }

       /// <summary>
        ///A test for ReadOnly
        ///</summary>
        [TestMethod()]
        public void ReadOnlyTest()
        {
            Type testClassType = typeof(TestTarget.TestFixtureSetupCorrect);
            MethodInfo testMethod = testClassType.GetMethod("HasBeenSetup");

            DummyTest test = new DummyTest();
            test.TestName = new NUnitSide.TestName();

            test.TestName.FullName = testClassType.FullName + "." + testMethod.Name;
            test.TestName.Name = testMethod.Name;
            test.TestType = testClassType.FullName;
            Assembly assembly = testClassType.Assembly;

            UnitTest target = new UnitTest(test, assembly.Location);
            Assert.AreEqual(false, target.ReadOnly, "Default should be false");
            target.ReadOnly = true;
            Assert.AreEqual(true, target.ReadOnly, "Should be editable to true");
            target.ReadOnly = false;
            Assert.AreEqual(false, target.ReadOnly, "Should be editable to false");
        }

        /// <summary>
        ///A test for Namespace
        ///</summary>
        [TestMethod()]
        public void NamespaceTest()
        {
            Type testClassType = typeof(TestTarget.TestFixtureSetupCorrect);
            MethodInfo testMethod = testClassType.GetMethod("HasBeenSetup");

            DummyTest test = new DummyTest();
            test.TestName = new NUnitSide.TestName();

            test.TestName.FullName = testClassType.FullName + "." + testMethod.Name;
            test.TestName.Name = testMethod.Name;
            test.TestType = testClassType.FullName;
            Assembly assembly = testClassType.Assembly;

            UnitTest target = new UnitTest(test, assembly.Location);
            string actual;
            actual = target.Namespace;

            string expected = testClassType.Namespace;

            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///A test for Name
        ///</summary>
        [TestMethod()]
        public void NameTest()
        {
            Type testClassType = typeof(TestTarget.TestFixtureSetupCorrect);
            MethodInfo testMethod = testClassType.GetMethod("HasBeenSetup");

            DummyTest test = new DummyTest();
            test.TestName = new NUnitSide.TestName();

            test.TestName.FullName = testClassType.FullName + "." + testMethod.Name;
            test.TestName.Name = testMethod.Name;
            test.TestType = testClassType.FullName;
            Assembly assembly = testClassType.Assembly;

            UnitTest target = new UnitTest(test, assembly.Location);
            string actual;
            actual = target.Namespace;

            string expected = testClassType.Namespace;

            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///A test for Microsoft.VisualStudio.TestTools.Common.IHostedTest.HostType
        ///</summary>
        [TestMethod()]
        public void HostTypeTest()
        {
            UnitTest target = CreateNUnitTestElement();

            string expected = Guid.NewGuid().ToString();
            string actual;
            target.HostType = expected;
            actual = target.HostType;
            Assert.AreEqual(expected, actual);
        }

        private static UnitTest CreateNUnitTestElement()
        {
            Type testClassType = typeof(TestTarget.TestFixtureSetupCorrect);
            MethodInfo testMethod = testClassType.GetMethod("HasBeenSetup");
            DummyTest test = new DummyTest();
            test.TestName = new NUnitSide.TestName();
            test.TestName.FullName = testClassType.FullName + "." + testMethod.Name;
            test.TestName.Name = testMethod.Name;
            test.TestType = testClassType.FullName;
            Assembly assembly = testClassType.Assembly;

            UnitTest target = new UnitTest(test, assembly.Location);
            return target;
        }

        /// <summary>
        ///A test for HumanReadableId
        ///</summary>
        [TestMethod()]
        public void HumanReadableIdTest()
        {
            UnitTest target = CreateNUnitTestElement();
            string actual;
            actual = target.HumanReadableId;
            string expected = "NUnitTest.UnitTest.Targets.TestFixtureSetupCorrect.HasBeenSetup";
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///A test for FullyQualifiedClassName
        ///</summary>
        [TestMethod()]
        public void FullyQualifiedClassNameTest()
        {
            UnitTest target = CreateNUnitTestElement();
            string actual;
            actual = target.FullyQualifiedClassName;
            Assert.AreEqual("NUnitTest.UnitTest.Targets.TestFixtureSetupCorrect", actual);
        }

        /// <summary>
        ///A test for Copy
        ///</summary>
        [TestMethod()]
        public void CopyTest()
        {
            UnitTest target = CreateNUnitTestElement();
            MSTestSide.ITestElement actual;
            actual = target.Copy;
            Assert.AreEqual(target, actual);
        }

        /// <summary>
        ///A test for ControllerPlugin
        ///</summary>
        [TestMethod()]
        public void ControllerPluginTest()
        {
            UnitTest target = CreateNUnitTestElement();
            string actual;
            actual = target.ControllerPlugin;
            Assert.AreEqual(null, actual);
        }

        /// <summary>
        ///A test for CodeBase
        ///</summary>
        [TestMethod()]
        public void CodeBaseTest()
        {
            UnitTest target = CreateNUnitTestElement();
            string actual;
            actual = Path.GetFullPath(target.CodeBase);

            string expected = Path.GetFullPath(typeof(TestTarget.TestFixtureSetupCorrect).Assembly.Location);

            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///A test for ClassName
        ///</summary>
        [TestMethod()]
        public void ClassNameTest()
        {
            UnitTest target = CreateNUnitTestElement();
            string actual;
            actual = target.ClassName;
            Assert.AreEqual(typeof(TestTarget.TestFixtureSetupCorrect).Name, actual);

        }

        /// <summary>
        ///A test for CanBeAggregated
        ///</summary>
        [TestMethod()]
        public void CanBeAggregatedTest()
        {
            UnitTest target = CreateNUnitTestElement();
            bool actual;
            actual = target.CanBeAggregated;
            Assert.AreEqual(true, actual);
        }

        /// <summary>
        ///A test for Adapter
        ///</summary>
        [TestMethod()]
        public void AdapterTest()
        {
            UnitTest target = CreateNUnitTestElement();
            string actual;
            actual = target.Adapter;
            Assert.AreEqual(typeof(NUnitTestAdapter).AssemblyQualifiedName, actual);
        }

        /// <summary>
        ///A test for Clone
        ///</summary>
        [TestMethod()]
        public void CloneTest()
        {
            UnitTest target = CreateNUnitTestElement();
            UnitTest actual;
            actual = target.Clone() as UnitTest;
            Assert.AreEqual(target, actual);
            Assert.AreNotSame(target, actual);
            Assert.AreEqual(target.Name, actual.Name);
            Assert.AreEqual(target.FullyQualifiedClassName, actual.FullyQualifiedClassName);
            Assert.AreEqual(target.ClassName, actual.ClassName);
            Assert.AreEqual(target.CodeBase, actual.CodeBase);
        }

        /// <summary>
        ///A test for NUnitTestElement Constructor
        ///both Vallues Null
        ///</summary>
        [TestMethod()]
        [ExpectedException(typeof(ArgumentException))]
        public void NUnitTestElementConstructorTestNullTestNullAssembly()
        {
            NUnitSide.ITest test = null;
            UnitTest target = new UnitTest(test, null);
        }

        /// <summary>
        ///A test for NUnitTestElement Constructor
        ///</summary>
        [TestMethod()]
        [ExpectedException(typeof(ArgumentNullException))]
        public void NUnitTestElementConstructorTestTestNullAssembly()
        {
            DummyTest test = new DummyTest();
            test.TestName = new NUnitSide.TestName();
            test.TestName.Name = "Test";
            UnitTest target = new UnitTest(test, null);
        }

        /// <summary>
        ///A test for NUnitTestElement Constructor
        ///</summary>
        [TestMethod()]
        [ExpectedException(typeof(ArgumentException))]
        public void NUnitTestElementConstructorTestNullTestAssembly()
        {
            NUnitSide.ITest test = null;
            Assembly assembly = this.GetType().Assembly;
            UnitTest target = new UnitTest(test, assembly.Location);
        }

        /// <summary>
        ///A test for NUnitTestElement Constructor with an invalide Assembly for the class
        ///</summary>
        [TestMethod()]
        public void NUnitTestElementConstructorTest()
        {
            Type testClassType = typeof(TestTarget.TestFixtureSetupCorrect);
            MethodInfo testMethod = testClassType.GetMethod("HasBeenSetup");

            DummyTest test = new DummyTest();
            test.TestName = new NUnitSide.TestName();

            test.TestName.FullName = testClassType.FullName + "." + testMethod.Name;
            test.TestName.Name = testMethod.Name;
            test.TestType = testClassType.FullName;
            Assembly assembly = testClassType.Assembly;

            UnitTest target = new UnitTest(test, assembly.Location);
            Assert.AreEqual(target.ClassName, testClassType.Name);
            Assert.AreEqual(target.FullyQualifiedClassName, testClassType.FullName);
        }

        /// <summary>
        ///A test for FillDataRows
        ///</summary>
        [TestMethod()]
        public void NUnitTestElementFillDataRowTest()
        {
            Type testClassType = typeof(TestTarget.TestFixtureSetupCorrect);
            MethodInfo testMethod = testClassType.GetMethod("HasBeenSetup");

            DummyTest test = new DummyTest();
            test.TestName = new NUnitSide.TestName();

            test.TestName.FullName = testClassType.FullName + "." + testMethod.Name;
            test.TestName.Name = testMethod.Name;
            test.TestType = testClassType.FullName;
            Assembly assembly = testClassType.Assembly;

            UnitTest target = new UnitTest(test, assembly.Location);

            DataTable table = new DataTable("test");
            DataColumnCollection col = table.Columns;

            col.Add("object_column", typeof(object));
            col.Add("ClassName", typeof(string));
            col.Add("Namespace", typeof(string));
            col.Add("HumanReadableId", typeof(string));
            col.Add("Owner", typeof(string));
            col.Add("CreatedByUI", typeof(string));
            col.Add("SolutionName", typeof(string));
            col.Add("Enabled", typeof(string));
            col.Add("ProjectData", typeof(string));
            col.Add("IsRunnable", typeof(string));
            col.Add("Name", typeof(string));
            col.Add("TestType", typeof(string));
            col.Add("TimeoutVisible", typeof(string));
            col.Add("CanBeAggregated", typeof(string));
            col.Add("IsAutomated", typeof(string));
            col.Add("ProjectName", typeof(string));
            col.Add("Priority", typeof(string));
            col.Add("ErrorMessageForNonRunnable", typeof(string));
            col.Add("ProjectRelativePath", typeof(string));
            col.Add("SourceFileName", typeof(string));
            col.Add("Storage", typeof(string));
            col.Add("Description", typeof(string));
            DataRow row = table.NewRow();
            target.FillDataRow(row);
            //Second time
            target.FillDataRow(row);
        }
    }
}
